use askama::Template;
use askama_axum::IntoResponse;
use axum::{extract::{Path, Query, State}, Form};

use crate::{core::AppState, services::frontend::{blog_service::BlogService, category_service::CategoryService, collect_service::CollectService, product_service::ProductService, taxon_service::TaxonService}, types::{common::{CategoryListReq, PageListReq}, frontend::{blog_type::{BlogDetail, BlogRow}, category_type::CategoryRow, collect_type::{CollectListResp, CollectTypeRow, SwReq}, feedback_type::FeedbackForm, product_type::{ProductDetail, ProductRow}, taxon_type::TaxonRow}}};

use super::{ErrorTemplate, FrontendFragment};

#[derive(Template)]
#[template(path = "frontend/index.html")]
struct IndexTemplate {
    seo: FrontendFragment,
    categorys: Vec<CategoryRow>,
    blogs: Vec<BlogRow>
}

#[derive(Template)]
#[template(path = "frontend/category.html")]
struct CategoryTemplate {
    seo: FrontendFragment,
    categorys: Vec<CategoryRow>,
    blogs: Vec<BlogRow>,
    paginate: String,
}

#[derive(Template)]
#[template(path = "frontend/article.html")]
struct ArticleTemplate {
    seo: FrontendFragment,
    categorys: Vec<CategoryRow>,
    blog: BlogDetail,
    category: CategoryRow,
    related_blogs: Vec<BlogRow>
}

#[derive(Template)]
#[template(path = "frontend/taxon.html")]
struct TaxonTemplate {
    seo: FrontendFragment,
    taxons: Vec<TaxonRow>,
    products: Vec<ProductRow>,
    paginate: String,
}

#[derive(Template)]
#[template(path = "frontend/product.html")]
struct ProductTemplate {
    seo: FrontendFragment,
    taxons: Vec<TaxonRow>,
    product: ProductDetail,
    taxon: TaxonRow
}

#[derive(Template)]
#[template(path = "frontend/collect.html")]
struct CollectTemplate {
    seo: FrontendFragment,
    types: Vec<CollectTypeRow>,
    collects: Vec<CollectListResp>
}

#[derive(Template)]
#[template(path = "frontend/feedback.html")]
struct FeedbackTemplate {
    seo: FrontendFragment,
    data: FeedbackForm,
    msg: String
}

/// 首页
pub async fn home_handler(State(state):State<AppState>) -> impl IntoResponse {
    let seo = FrontendFragment::init(&state.db, "", "", "").await;
    // 获取所有文章分类
    let categorys_res = CategoryService::get_categorys(&state.db).await;
    let categorys = match categorys_res {
        Ok(data) => data,
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };

    // 获取最新5条博客
    let blog_res = BlogService::get_newest(&state.db, 5).await;
    let blogs = match blog_res {
        Ok(data) => data,
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };

    let template = IndexTemplate{
        seo,
        categorys,
        blogs
    };
    return axum::response::Html(template.render().unwrap())
}

/// 文章分类
pub async fn list_blog_handler(State(state):State<AppState>, Query(args):Query<CategoryListReq>) -> impl IntoResponse {
    let seo = FrontendFragment::init(&state.db, "", "", "").await;
    // 获取所有文章分类
    let categorys_res = CategoryService::get_categorys(&state.db).await;
    let categorys = match categorys_res {
        Ok(data) => data,
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };

    let blogs_res = BlogService::get_blog_page(&state.db, &args).await;
    match blogs_res {
        Ok(data) => {
            let template = CategoryTemplate{
                seo,
                categorys,
                blogs: data.list,
                paginate: data.paginate
            };
            return axum::response::Html(template.render().unwrap())
        },
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };
}

/// 文章详情
pub async fn detail_blog_handler(State(state):State<AppState>, Path(id):Path<i64>) -> impl IntoResponse {
    let seo = FrontendFragment::init(&state.db, "", "", "").await;
    // 获取所有文章分类
    let categorys_res = CategoryService::get_categorys(&state.db).await;
    let categorys = match categorys_res {
        Ok(data) => data,
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };


    let blog_res = BlogService::get_blog_by_id(&state.db, id).await;
    match blog_res {
        Ok(data) => {
            // 相关推荐
            let related_res = BlogService::get_related(&state.db, data.cid, 4).await;
            let related_blogs = match related_res {
                Ok(related) => related,
                Err(e) => {
                    let template = ErrorTemplate{
                        msg: e.to_string()
                    };
                    return axum::response::Html(template.render().unwrap())
                }
            };
            let mut category = CategoryRow {
                id: data.cid,
                name: "".to_string(),
                image: "".to_string(),
                num: 0
            };
            for cat in categorys.clone() {
                if data.cid == cat.id {
                    category.name = cat.name;
                    category.image = cat.image;
                    category.num = cat.num;
                }
            }
            // 更新点击
            let hits = data.hits + 1;
            let _ = BlogService::update_hits(&state.db, id, hits).await;
            let template = ArticleTemplate{
                seo,
                categorys,
                blog: data,
                category,
                related_blogs
            };
            return axum::response::Html(template.render().unwrap())
        },
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    }
}

/// 产品分类
pub async fn list_product_handler(State(state):State<AppState>, Query(args):Query<CategoryListReq>) -> impl IntoResponse {
    let seo = FrontendFragment::init(&state.db, "", "", "").await;
    // 获取所有产品分类
    let taxons_res = TaxonService::get_taxons(&state.db).await;
    let taxons = match taxons_res {
        Ok(data) => data,
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };

    let products_res = ProductService::get_product_page(&state.db, &args).await;
    match products_res {
        Ok(data) => {
            let template = TaxonTemplate{
                seo,
                taxons,
                products: data.list,
                paginate: data.paginate
            };
            return axum::response::Html(template.render().unwrap())
        },
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };
}

/// 产品详情
pub async fn detail_product_handler(State(state):State<AppState>, Path(id):Path<i64>) -> impl IntoResponse {
    let seo = FrontendFragment::init(&state.db, "", "", "").await;
    // 获取所有产品分类
    let taxons_res = TaxonService::get_taxons(&state.db).await;
    let taxons = match taxons_res {
        Ok(data) => data,
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };


    let product_res = ProductService::get_product_by_id(&state.db, id).await;
    match product_res {
        Ok(data) => {
            let mut taxon = TaxonRow {
                id: data.tid,
                name: "".to_string(),
                image: "".to_string(),
                num: 0
            };
            for cat in taxons.clone() {
                if data.tid == cat.id {
                    taxon.name = cat.name;
                    taxon.image = cat.image;
                    taxon.num = cat.num;
                }
            }
            // 更新点击
            let hits = data.hits + 1;
            let _ = ProductService::update_hits(&state.db, id, hits).await;
            let template = ProductTemplate{
                seo,
                taxons,
                product: data,
                taxon
            };
            return axum::response::Html(template.render().unwrap())
        },
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    }
}

/// 收藏
pub async fn list_collect_handler(State(state):State<AppState>, Query(args):Query<SwReq>) -> impl IntoResponse {
    let seo = FrontendFragment::init(&state.db, "", "", "").await;
    // 获取所有产品分类
    let types_res = CollectService::get_types(&state.db).await;
    let types = match types_res {
        Ok(data) => data,
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };

    let collects_res = CollectService::get_collects(&state.db, &args).await;
    match collects_res {
        Ok(data) => {
            let template = CollectTemplate{
                seo,
                types,
                collects: data 
            };
            axum::response::Html(template.render().unwrap())
        },
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            axum::response::Html(template.render().unwrap())
        }
    }
}

/// 反馈
pub async fn add_feedback_handler(State(state):State<AppState>) -> impl IntoResponse {
    let seo = FrontendFragment::init(&state.db, "", "", "").await;
    let template = FeedbackTemplate {
        seo,
        data: FeedbackForm{
            title: "".to_string(), 
            email: "".to_string(),
            content: "".to_string()
        },
        msg: "".to_string()
    };
    axum::response::Html(template.render().unwrap())
}


pub async fn create_feedback_handler(State(state): State<AppState>, Form(form):Form<FeedbackForm>) -> impl IntoResponse {
    let seo = FrontendFragment::init(&state.db, "", "", "").await;
    
    let template = FeedbackTemplate {
        seo,
        data: FeedbackForm{
            title: "".to_string(), 
            email: "".to_string(),
            content: "".to_string()
        },
        msg: "".to_string()
    };
    axum::response::Html(template.render().unwrap())
}